using System;
using System.IO;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;

namespace My.IdlConverter.Core
{
    using Parsers;
    using Filters;
    using Cfg;

    public static class Component
    {
        public static string[] SpecialInterfaceCluewords = 
        {
            "Document",
            "Layer",
            "Shape",
            "GraphicsItem",
            "ColumnTextItem",
            "ImageItem",
            "TableItem",
            "DocWindow",
            "ToolBar",
            "ParamTemplates",
            "ParamTemplate",
            "TextLine",
            "Article",
            "Font",
            "FontFamily",
            "Line",
            "SpreadItem"

        };

        public static IDictionary<string, string> MethodNameInterfaceName = new Dictionary<string, string>();

        static Component()
        {
            MethodNameInterfaceName.Add("GetGraphics","IGraphics");
//            MethodNameInterfaceName.Add("GetGraphics", "IGraphics");
        }

        public static string Name
        {
            get
            {
                return "WinScriptEngine";
            }
        }

        public static IList<Class> Classes
        {
            get
            {
                IList<Class> classes = new List<Class>();

                IList<Class> sealedClasses = SealedClasses;
                foreach (Class nextClassObj in sealedClasses)
                {
                    classes.Add(nextClassObj);
                    if (nextClassObj.HasBaseClass)
                    {
                        IList<Class> baseClassesOfTheClass = new List<Class>();
                        nextClassObj.GetBaseClasses(ref baseClassesOfTheClass);
                        foreach (Class nextBaseClassObj in baseClassesOfTheClass)
                        {
                            classes.Add(nextBaseClassObj);
                        }
                    }
                }

                return classes;
            }
        }

        public static IList<Class> SealedClasses
        {
            get
            {
                IList<Graphics.ClassTree> trees = Graphics.ClassForest.Instance.ChildTrees;
                IList<Class> sealedClasses = new List<Class>();
                foreach (Graphics.ClassTree nextTree in trees)
                {
                    Class classObj = nextTree.ReferObj as Class;
                    Debug.Assert(classObj != null);
                    sealedClasses.Add(classObj);
                }

                return sealedClasses;
            }
        }

        private static bool FindInterface(IList<Interface> interfaces, Interface obj)
        {
            if (interfaces.Count == 0)
                return false;
            if (obj == null)
                return false;
            foreach (Interface nextInterface in interfaces)
            {
                if (nextInterface.Equals(obj))
                    return true;
            }

            return false;
        }

        public static IList<Interface> Interfaces
        {
            get
            {
                IList<Interface> interfaces = new List<Interface>();
                IList<Class> sealedClasses = SealedClasses;
                foreach (Class nextClassObj in sealedClasses)
                {
                    IList<Interface> baseInterfacesOfClass = new List<Interface>();
                    nextClassObj.GetPureBaseInterfaces(ref baseInterfacesOfClass);
                    foreach (Interface nextInterfaceObj in baseInterfacesOfClass)
                    {
                        if (!FindInterface(interfaces,nextInterfaceObj))
                            interfaces.Add(nextInterfaceObj);
                    }
                }

                return interfaces;
            }
        }

        public static Interface ExactFindInterface(string clueWord)
        {
            IList<Interface> interfaces = Interfaces;
            foreach (Interface nextInterfaceObj in interfaces)
            {
                if (nextInterfaceObj.Name.IndexOf(clueWord) != -1)
                    return nextInterfaceObj;
                else if (clueWord.IndexOf(nextInterfaceObj.ClueWord) != -1)
                    return nextInterfaceObj;
            }

            throw new Exceptions.InterfaceNotFoundException("Interface not found",clueWord);
        }

        public static Interface QuickFindInterface(string clueWord)
        {
            string interfaceFileName = "Iv_DOM" + clueWord + ".h";
            string interfacePathName = Path.Combine(Configuration.InterfaceFolder, interfaceFileName);
            IParser interfaceParser = new InterfaceParser();
            Interface interfaceObj = interfaceParser.Parse(interfacePathName) as Interface;
            if (interfaceObj != null)
                return interfaceObj;

            throw new Exceptions.InterfaceNotFoundException("Interface not found", clueWord);
        }

        public static string MiscellaneouFindInterface(Interface methodParent)
        {
            Interface theInterfaceObj = methodParent;
            if (methodParent.IsClass())
            {
                theInterfaceObj = (methodParent as Class).DefaultBaseInterface;
            }
            string interfaceName = "";
            if (theInterfaceObj != null)
            {
                interfaceName = theInterfaceObj.Name;
                interfaceName = Util.StringUtil.ChangeToSingular(interfaceName);
            }
            return interfaceName;
        }

        public static string FindInterfaceBy(Method methodObj)
        {
            string methodName = methodObj.Name;
            string retInterfaceName = "";
            if (methodName.Equals("Get")
                || methodName.Equals("Clone")
                || methodName.Equals("New")
                || methodName.Equals("Add")
                || methodName.Equals("Create"))
            {
                retInterfaceName = MiscellaneouFindInterface(methodObj.Parent);
            }
            else if (methodObj.Getter)
            {
                methodName = methodName.Remove(0, "Get".Length);
                Interface interfaceObj = null;
                try
                {
                    interfaceObj = QuickFindInterface(methodName);
                    retInterfaceName = interfaceObj.Name;
                }
                catch (Exceptions.InterfaceNotFoundException e1)
                {
                    Trace.Write(e1.Message);
                    try
                    {
                        interfaceObj = ExactFindInterface(methodName);
                        retInterfaceName = interfaceObj.Name;
                    }
                    catch (Exceptions.InterfaceNotFoundException e2)
                    {
                        Trace.Write(e2.Message);
                        retInterfaceName = MiscellaneouFindInterface(methodObj.Parent);
                    }
                }
            }
            else
            {
                try
                {
                    string keyword = Util.ArrayHelper.FindKeyword(SpecialInterfaceCluewords, methodName);
                    return ("I"+keyword);
                }
                catch(KeyNotFoundException e)
                {
                    Trace.Write(e.Message);
                }
            }
            if (retInterfaceName.Length > 0)
                return InterfaceModifier.GetName(retInterfaceName);
            else
            {
                Trace.Write("The interface can not be parsed : "+methodObj.Parent.Name);
                return "";
            }
        }
    }
}
